//package org.mat.framework.service.context;
//
//import com.netflix.hystrix.strategy.HystrixPlugins;
//import com.netflix.hystrix.strategy.concurrency.HystrixConcurrencyStrategy;
//import com.netflix.hystrix.strategy.eventnotifier.HystrixEventNotifier;
//import com.netflix.hystrix.strategy.executionhook.HystrixCommandExecutionHook;
//import com.netflix.hystrix.strategy.metrics.HystrixMetricsPublisher;
//import com.netflix.hystrix.strategy.properties.HystrixPropertiesStrategy;
//import lombok.extern.slf4j.Slf4j;
//import org.slf4j.MDC;
//import org.springframework.web.context.request.RequestAttributes;
//import org.springframework.web.context.request.RequestContextHolder;
//
//import java.util.Map;
//import java.util.concurrent.Callable;
//
///**
// * @ClassName: RequestContextHystrixConcurrencyStrategy
// * @Date: 2021/8/17
// * @author: sunxinhe
// * @Version: 1.0
// * @Description: TODO
// * <p>
// * 参考：
// * https://www.itmuch.com/spring-cloud-sum/hystrix-threadlocal/
// * https://github.com/spring-cloud/spring-cloud-netflix/pull/2509
// */
//@Slf4j
//public class RequestContextHystrixConcurrencyStrategy extends HystrixConcurrencyStrategy {
//    private HystrixConcurrencyStrategy delegate;
//
//    public RequestContextHystrixConcurrencyStrategy() {
//        try {
//            this.delegate = HystrixPlugins.getInstance().getConcurrencyStrategy();
//            if (this.delegate instanceof RequestContextHystrixConcurrencyStrategy) {
//                // Welcome to singleton hell...
//                return;
//            }
//            HystrixCommandExecutionHook commandExecutionHook = HystrixPlugins
//                    .getInstance().getCommandExecutionHook();
//            HystrixEventNotifier eventNotifier = HystrixPlugins.getInstance()
//                    .getEventNotifier();
//            HystrixMetricsPublisher metricsPublisher = HystrixPlugins.getInstance()
//                    .getMetricsPublisher();
//            HystrixPropertiesStrategy propertiesStrategy = HystrixPlugins.getInstance()
//                    .getPropertiesStrategy();
//            this.logCurrentStateOfHystrixPlugins(eventNotifier, metricsPublisher,
//                    propertiesStrategy);
//            HystrixPlugins.reset();
//            HystrixPlugins.getInstance().registerConcurrencyStrategy(this);
//            HystrixPlugins.getInstance()
//                    .registerCommandExecutionHook(commandExecutionHook);
//            HystrixPlugins.getInstance().registerEventNotifier(eventNotifier);
//            HystrixPlugins.getInstance().registerMetricsPublisher(metricsPublisher);
//            HystrixPlugins.getInstance().registerPropertiesStrategy(propertiesStrategy);
//        } catch (Exception e) {
//            log.error("Failed to register Sleuth Hystrix Concurrency Strategy", e);
//        }
//    }
//
//    private void logCurrentStateOfHystrixPlugins(HystrixEventNotifier eventNotifier,
//                                                 HystrixMetricsPublisher metricsPublisher,
//                                                 HystrixPropertiesStrategy propertiesStrategy) {
//        if (log.isDebugEnabled()) {
//            log.debug("Current Hystrix plugins configuration is ["
//                    + "concurrencyStrategy [" + this.delegate + "]," + "eventNotifier ["
//                    + eventNotifier + "]," + "metricPublisher [" + metricsPublisher + "],"
//                    + "propertiesStrategy [" + propertiesStrategy + "]," + "]");
//            log.debug("Registering Sleuth Hystrix Concurrency Strategy.");
//        }
//    }
//
//    @Override
//    public <T> Callable<T> wrapCallable(Callable<T> callable) {
//        return new RequestAttributeAwareCallable<>(callable, RequestContextHolder.getRequestAttributes());
//    }
//
//    static class RequestAttributeAwareCallable<T> implements Callable<T> {
//
//        private final Callable<T> target;
//        private final RequestAttributes parentRequestAttributes;
//        private final Map parentMDC;
//
//        public RequestAttributeAwareCallable(Callable<T> callable, RequestAttributes parentRequestAttributes) {
//            this.target = callable;
//            this.parentRequestAttributes = parentRequestAttributes;
//            this.parentMDC = MDC.getCopyOfContextMap();
//        }
//
//        @Override
//        public T call() throws Exception {
//            // 调用前清理，避免子线程出现ThreadLocal脏数据
//            MDC.clear();
//            RequestContextHolder.resetRequestAttributes();
//
//            // 传递父线程RequestAttributes和MDC
//            MDC.setContextMap(parentMDC);
//            RequestContextHolder.setRequestAttributes(parentRequestAttributes);
//            return target.call();
//
//
//        }
//    }
//
//}
